<?php 

class App_AclFactory {
	/**
   * Creates an ACL for a specific page
   * @param Page $page
   * @return Zend_Acl
   */
	public function createAcl(Model_Page $page) {
		//Lets assume we have a model for the page_privileges with a method like this
		//which would return PagePrivilege objects with the page_id passed as the param.
		$privileges = Model_PagePrivilege::findByPageId($page->getId());

		$acl = new Zend_Acl();
		$acl->add(new Zend_Acl_Resource($page->getId()));

		foreach($privileges as $privilege) {
			$acl->addRole(new Zend_Acl_Role($privilege->getUserId()));
			$acl->allow($privilege->getUserId(), $page->getId());
		}
		return $acl;
	}

	public function createCategoryAcl(Model_Category $category, Model_User $user) {
		$acl = new Zend_Acl();
		$this->_createRoles($acl, $user);

		//$categories = $category->getParents() + array($category);
		$categories = array_merge($category->getParents(), array($category));      
      
		//Top category has no parent, so it's null at first
		$parent = null;
		foreach($categories as $c) {
			$acl->add($c, $parent);
			//next will have this as the parent
			$parent = $c;
		}
		$privileges = Model_Privilege::findByCategories($categories);
		$this->_setPrivileges($acl, $privileges);
		return $acl;
	}

	private function _createRoles(Zend_Acl $acl, Model_User $user) {
		//add groups first so user can inherit them
		foreach($user->getGroups() as $group) {
			$acl->addRole($group);
		}
		$acl->addRole($user, $user->getGroups());
	}

	private function _setPrivileges($acl, $privileges) {
	   foreach($privileges as $privilege) {
			$role = $privilege->getRole();
			$resource = $privilege->getResource();
			//the user's roles should already exist so we can ignore the ones that don't
			if(!$acl->hasRole($role)) {
				continue;
			}

			if($privilege->getMode() == 'allow') {
				$acl->allow($role, $resource);
			} else {
				$acl->deny($role, $resource);
			}
		}
	}

	public function createFileAcl(Model_File $file, Model_User $user) {
		$acl = null;
		if($file->getCategoryId() != null) {
			//if the file belongs to a category
			//we need to build the whole category based acl
			$category = $file->getCategory();
			$acl = $this->createCategoryAcl($category, $user);
			$acl->add($file, $category);
		}
		else {
			$acl = new Zend_Acl();
			$this->_createRoles($acl, $user);
			$acl->add($file);
		}

		$privileges = Model_Privilege::findByFile($file);
		$this->_setPrivileges($acl, $privileges);
		return $acl;
	}
	
	
}